package com.system.demo.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.system.demo.commonService.RabbitMQService;
import com.system.demo.entity.DTO.LeaveIdDTO;
import com.system.demo.entity.DTO.LeaveRequestDTO;
import com.system.demo.entity.DTO.LeaveSearchDTO;
import com.system.demo.entity.database.Leave;
import com.system.demo.entity.database.UserNotifications;
import com.system.demo.mapper.LeaveMapper;
import com.system.demo.service.LeaveService;
import com.system.demo.tool.ResponseResult;
import com.system.demo.utils.MinioUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;



import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


import static com.system.demo.service.constant.ApplicationStatus.MINIO_LEAVE_PATH;
import static com.system.demo.service.constant.LeaveStatusConstant.*;
import static com.system.demo.service.constant.UserNotificationConstant.NO_CHECK;

@Service
public class LeaveServiceImpl implements LeaveService {

    @Autowired
    private LeaveMapper leaveMapper;

    @Value("${minio.bucketName}")
    private String bucketName;

    @Autowired
    private MinioUtils minioUtils;

    @Autowired
    private RabbitMQService rabbitMQService;

    @Value("${myIp.ip}")
    private String ip;

    @Value("${minio.port}")
    private int port;




    /**
     * 管理员离校申请查询：
     *
     * @param leaveSearchDTO 前端提交的离校申请查询表单
     * @param current 页号
     * @param size 页面大小
     * @return 返回信息
     */
    @Override
    public ResponseResult<?> requestLeave(LeaveSearchDTO leaveSearchDTO, int current, int size) {
        // 处理空字符串
        try {


            // 创建分页对象
            Page<Leave> page = new Page<Leave>();


            // 查询条件
            Integer stuClass = leaveSearchDTO.getStuClass();
            String grade = null;
            if (stuClass != null) {
                 grade = String.valueOf((LocalDateTime.now().getYear() - stuClass + 1)).substring(2);
            }
            String uid = leaveSearchDTO.getUid();
            String userName = leaveSearchDTO.getUserName();
            String startTime = leaveSearchDTO.getStartTime();
            String endTime = leaveSearchDTO.getEndTime();
            Integer status = leaveSearchDTO.getStatus();

            // 调用 Mapper 查询
            Page<Leave> result = leaveMapper.selectLeaveByConditions(page, uid, userName, startTime, endTime, status, grade);

            // 返回分页数据
            return ResponseResult.success("查询成功", result.getTotal(), result.getRecords());
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.InternalServerError("服务器内部错误：" + e.getMessage());
        }
    }



    /**
     * 学生上传离校申请：
     *
     * @param leaveRequestDTO  需要上传离校申请的内容
     * @return 返回信息
     */

    @Override
    public ResponseResult<?> leavingSubmitApplication(LeaveRequestDTO leaveRequestDTO) {

        // 使用 DateTimeFormatter 指定日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        // 解析日期时间字符串
        LocalDateTime leavingTime = LocalDateTime.parse(leaveRequestDTO.getLeavingTime(), formatter);
        LocalDateTime backingTime = LocalDateTime.parse(leaveRequestDTO.getBackingTime(), formatter);
        LocalDateTime applicationTime = LocalDateTime.now();

        //判定离校时间是否距离申请时间少于一天
        if(Duration.between(applicationTime,leavingTime).toHours()<24) {
            return ResponseResult.BadRequest("时间太迟啦，下次要早点，联系管理员叭~");
        }
        String uid = StpUtil.getLoginId().toString();
        String stuName = leaveMapper.findStudentNameByUid(uid);
        String stuClass = leaveMapper.findStudentNameByClass(uid);

        if(stuName == null){
            return ResponseResult.NotFound("未找到用户对应的名字");
        }
        Leave leave = new Leave();
        leave.setUid(uid);
        leave.setUserName(stuName);
        leave.setStuClass(stuClass);
        leave.setReason(leaveRequestDTO.getReason());
        leave.setPosition(leaveRequestDTO.getPosition());
        leave.setLeavingTime(leavingTime);
        leave.setBackingTime(backingTime);
        //传入联系电话
        leave.setNumber(leaveRequestDTO.getNumber());
        //传入申请时间
        leave.setApplicationTime(applicationTime);
        leave.setStatus(APPLIED);
        //上传图片


        /*
         * 上传文件到MinIO服务器
         *
         * @param file 要上传的文件
         * @param bucketName 桶名
         * @param path 文件保存的路径（不包含文件名） 学号/leave
         * @param objectName 对象名称（即文件名）
         * @return 如果上传成功返回true，否则返回false
         */
        try{
            //在minio中以学号创建文件夹
            String stuId = StpUtil.getLoginId().toString();
            String path = stuId +"/"+MINIO_LEAVE_PATH;
            String objectName = leaveRequestDTO.getPicture().getOriginalFilename();

            boolean uploadSuccess = minioUtils.uploadFile(leaveRequestDTO.getPicture(), bucketName, path, objectName);
            if (!uploadSuccess) {
                return ResponseResult.InternalServerError("文件上传失败");
            }

            String fileUrl = "http://" + ip + ":" + port + "/" + bucketName + "/" + path + "/" + objectName;

            leave.setUrl(fileUrl);

            if(!(leaveMapper.insert(leave) > 0)) {
                return  ResponseResult.InternalServerError("文件信息保存失败");
            }

            return ResponseResult.success("文件上传成功");

            }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.InternalServerError("服务器内部错误" + e.getMessage());
        }

    }

    /**
     * 管理员批量审批：
     *
     * @param applicationId  数据库对应数据id
     * @param isApproved     修改申请状态（0变成1或2，1为已审批未通过，2为已审批已通过）
     * @return 返回信息
     */

    @Override
    public ResponseResult<?> changeLeave(LeaveIdDTO applicationId, String isApproved) {
        try {
            // 1. 获取审批的 ID 列表
            List<Integer> applicationIds = applicationId.getApplicationId(); // 从 DTO 中提取 ID 列表
            if (applicationIds == null || applicationIds.isEmpty()) {
                return ResponseResult.NotFound("未查询到对应记录");
            }

            // 查询记录，确保其状态正确
            List<Leave> leaveRecords = leaveMapper.selectBatchIds(applicationIds);
            if (leaveRecords == null || leaveRecords.isEmpty()) {
                return ResponseResult.NotFound("未查询到对应的申请记录");
            }

            // 确保所有记录的状态为 APPLIED
            for (Leave leave : leaveRecords) {
                if (leave.getStatus() != APPLIED) { // 假设 APPLIED 是 1
                    return ResponseResult.BadRequest("只有状态为 '待审批' 的申请才能进行审批");
                }
            }

            // 2. 确定新的审批状态
            int newStatus = "true".equalsIgnoreCase(isApproved) ? LEAVING_APPROVED : LEAVING_REJECTED; // 根据 isApproved 设置状态
            LocalDateTime approvalTime = LocalDateTime.now(); // 记录审批时间

            // 3. 转换 ID 列表为字符串 (如果方法需要 String 参数)
            String idListStr = applicationIds.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(",","(", ")"));

            // 3. 更新数据库
            int rowsUpdated = leaveMapper.batchUpdateStatus(idListStr, newStatus, approvalTime); // 假设这个方法支持批量更新
            if (rowsUpdated <= 0) {
                return ResponseResult.InternalServerError("批量审批失败");
            }

            if(newStatus == LEAVING_REJECTED){
                for( Leave leave: leaveRecords){
                    // 直接构建邮件内容并发送
                    String message = leave.getUserName() + "同学，您关于：《"
                            + leave.getReason() + "》的离校申请已被管理员驳回。";


                    UserNotifications notification = new UserNotifications();
                    notification.setUid(leave.getUid());
                    notification.setContent(message);
                    notification.setStatus(NO_CHECK);
                    notification.setCreatedTime(LocalDateTime.now());

                    rabbitMQService.sendNotification(notification);
                }
            }else{
                for( Leave leave: leaveRecords){
                    // 直接构建邮件内容并发送
                    String message = leave.getUserName() + "同学，您关于《"
                            + leave.getReason() + "》的离校申请已通过。";


                    UserNotifications notification = new UserNotifications();
                    notification.setUid(leave.getUid());
                    notification.setContent(message);
                    notification.setStatus(NO_CHECK);
                    notification.setCreatedTime(LocalDateTime.now());

                    rabbitMQService.sendNotification(notification);
                }
            }
            // 4. 返回成功信息
            return ResponseResult.success("批量审批成功，更新记录数: " + rowsUpdated);

        } catch (NumberFormatException e) {
            return ResponseResult.BadRequest("无效的审批状态值");
        } catch (Exception e) {
            return ResponseResult.InternalServerError("审批过程中发生错误: " + e.getMessage());
        }
    }





    /**
     * 学生撤回离校申请：
     *
     * @param id  数据库对应数据id
     * @return 返回信息
     */
    @Override
    public ResponseResult<?> leaveDelete(Integer id) {
        try {
            Leave application = leaveMapper.findByApplicationId(id);
            String Uid = StpUtil.getLoginId().toString();
            if (!Uid.equals(application.getUid())) {
                return ResponseResult.Forbidden("你又想干嘛？");
            }
            if (application.getStatus() != APPLIED){
                return ResponseResult.Forbidden("已经审批完成，无法撤回");
            }
            leaveMapper.deleteById(id,Uid);
            return ResponseResult.success("Leaving application deleted successfully.");
        } catch (Exception e) {
            // 记录异常信息
            e.printStackTrace();
            return ResponseResult.InternalServerError("Failed to delete application: " + e.getMessage());
        }
    }


    /**
     * 学生修改离校申请：
     *
     * @param applicationId  数据库对应数据id
     * @param leaveRequestDTO 前端传来的数据表单
     * @return 返回信息
     */

    @Override
    public ResponseResult<?> leaveApplicationUpdate(Integer applicationId, LeaveRequestDTO leaveRequestDTO) {
        try {
            // 1. 查询申请记录，确保其存在
            Leave existingLeave = leaveMapper.findByApplicationId(applicationId);
            if (existingLeave == null) {
                return ResponseResult.NotFound("未找到对应的申请记录");
            }
            // 2. 检查申请状态是否允许修改
            if (existingLeave.getStatus() != APPLIED) {
                return ResponseResult.BadRequest("当前状态不允许修改");
            }
            String Uid = StpUtil.getLoginId().toString();

            if(!Uid.equals(existingLeave.getUid())){
                return ResponseResult.Forbidden("你在做什么？");
            }

            // 3. 验证时间逻辑
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime leavingTime = LocalDateTime.parse(leaveRequestDTO.getLeavingTime(), formatter);
            LocalDateTime backingTime = LocalDateTime.parse(leaveRequestDTO.getBackingTime(), formatter);
            LocalDateTime applicationTime = LocalDateTime.now();

            if (Duration.between(applicationTime, leavingTime).toHours() < 24) {
                return ResponseResult.BadRequest("离校时间距离申请时间不足 24 小时，请重新选择时间");
            }

            // 4. 处理图片上传
            String fileUrl = existingLeave.getUrl(); // 默认保留原图片 URL
            if (leaveRequestDTO.getPicture() != null) {
                String stuId = StpUtil.getLoginId().toString();
                String path = stuId + "/" + MINIO_LEAVE_PATH;
                String objectName = leaveRequestDTO.getPicture().getOriginalFilename();

                boolean uploadSuccess = minioUtils.uploadFile(leaveRequestDTO.getPicture(), bucketName, path, objectName);
                if (!uploadSuccess) {
                    return ResponseResult.InternalServerError("文件上传失败");
                }

                fileUrl = "http://" + ip + ":" + port + "/" + bucketName + "/" + path + "/" + objectName;
            }

            // 5. 更新申请记录
            existingLeave.setReason(leaveRequestDTO.getReason());
            existingLeave.setPosition(leaveRequestDTO.getPosition());
            existingLeave.setLeavingTime(leavingTime);
            existingLeave.setBackingTime(backingTime);
            existingLeave.setNumber(leaveRequestDTO.getNumber());
            existingLeave.setUrl(fileUrl); // 更新图片 URL
            existingLeave.setApplicationTime(applicationTime);

            existingLeave.setApprovalTime(null);  // 清空审批时间
            existingLeave.setCheckingTime(null);  // 清空检查时间
            existingLeave.setApprovedTime(null);  // 清空批准时间
            int rowsUpdated = leaveMapper.updateLeave(existingLeave);

            if (rowsUpdated <= 0) {
                return ResponseResult.InternalServerError("更新申请记录失败");
            }

            // 6. 返回成功信息
            return ResponseResult.success("申请修改成功");

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.InternalServerError("服务器内部错误: " + e.getMessage());
        }
    }



    /**
     * 学生查看离校申请：
     *
     * @param current 页号
     * @param size 页面大小
     * @return 返回信息
     */

    @Override
    public ResponseResult<?> leavingView(int current, int size) {
        try{

            String stuUid = StpUtil.getLoginId().toString();
            LambdaQueryWrapper<Leave> queryWrapper = new LambdaQueryWrapper<>();
            if(stuUid != null){
                queryWrapper.eq(Leave::getUid, stuUid);
            }

            Page<Leave> page = new Page<>(current, size);

            Page<Leave> result = leaveMapper.selectPage(page,queryWrapper);

            return ResponseResult.success("查询成功",result.getTotal(),result.getRecords());

        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.InternalServerError("未知错误:"+e.getMessage());
        }
    }

    /**
     * 学生返校销假：
     *
     * @param applicationId 数据库id
     * @return 返回信息
     */

    @Override
    public ResponseResult<?> leaveApplicationBack(Integer applicationId) {
        try {
            // 1. 查询请假记录，确保该记录存在
            Leave leave = leaveMapper.findByApplicationId(applicationId);

            String Uid = StpUtil.getLoginId().toString();
            //检查销假账户与当前账户是否一致
            if (!Uid.equals(leave.getUid())) {
                return ResponseResult.Forbidden("不要做傻事！");
            }

            if (leave == null) {
                return ResponseResult.NotFound("未查询到对应的请假记录");
            }


            // 2. 检查当前状态是否为已审批已通过（状态 2）
            if (leave.getStatus() != LEAVING_APPROVED) {
                return ResponseResult.BadRequest("只有已审批已通过的请假才能进行销假操作");
            }

            //录入当时申请的时间
            LocalDateTime checkingTime = LocalDateTime.now();

            // 3. 更新状态为已申请销假（状态 3）
            int rowsUpdated = leaveMapper.updateLeaveStatus(applicationId, BACKING_APPLICATION, checkingTime); // 状态设置为 3（已申请销假）
            if (rowsUpdated <= 0) {
                return ResponseResult.InternalServerError("销假操作失败");
            }

            // 4. 返回成功信息
            return ResponseResult.success("销假申请操作成功");

        } catch (Exception e) {
            return ResponseResult.InternalServerError("销假过程中发生错误: " + e.getMessage());
        }

    }

    /**
     * 管理员审批销假申请：
     *
     * @param applicationId 数据库id
     * @param isApproved  是否已返校
     * @return 返回信息
     */

    public ResponseResult<?> approvalBack(LeaveIdDTO applicationId, String isApproved) {
        try {
            // 1. 获取审批的 ID 列表
            List<Integer> applicationIds = applicationId.getApplicationId(); // 从 DTO 中提取 ID 列表
            if (applicationIds == null || applicationIds.isEmpty()) {
                return ResponseResult.NotFound("未查询到对应记录");
            }

            // 查询记录，确保其状态正确
            List<Leave> leaveRecords = leaveMapper.selectBatchIds(applicationIds);
            if (leaveRecords == null || leaveRecords.isEmpty()) {
                return ResponseResult.NotFound("未查询到对应的申请记录");
            }

            // 确保所有记录的状态为 BACKING_APPLICATION
            for (Leave leave : leaveRecords) {
                if (leave.getStatus() != BACKING_APPLICATION) {
                    return ResponseResult.BadRequest("只有状态为 '待审批' 的申请才能进行审批");
                }
            }

            // 2. 确定新的审批状态
            int newStatus = "true".equalsIgnoreCase(isApproved) ? BACKING_APPROVED : BACKING_REJECTED; // 根据 isApproved 设置状态
            LocalDateTime approvedTime = LocalDateTime.now(); // 记录审批时间

            // 3. 转换 ID 列表为字符串 (如果方法需要 String 参数)
            String idListStr = applicationIds.stream()
                    .map(String::valueOf)
                    .collect(Collectors.joining(",","(", ")"));

            // 3. 更新数据库
            int rowsUpdated = leaveMapper.backupdateStatus(idListStr, newStatus, approvedTime); // 假设这个方法支持批量更新
            if (rowsUpdated <= 0) {
                return ResponseResult.InternalServerError("批量审批失败");
            }

            // 4. 返回成功信息
            return ResponseResult.success("批量审批成功，更新记录数: " + rowsUpdated);

        } catch (NumberFormatException e) {
            return ResponseResult.BadRequest("无效的审批状态值");
        } catch (Exception e) {
            return ResponseResult.InternalServerError("审批过程中发生错误: " + e.getMessage());
        }
    }
    }




